{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "25fe95cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2024-03-01 18:47:17.082 INFO    numexpr.utils: NumExpr defaulting to 8 threads.\n",
      "C:\\Users\\VR679RX\\Anaconda3\\envs\\pyenv\\lib\\site-packages\\pandas\\core\\arrays\\masked.py:60: UserWarning: Pandas requires version '1.3.6' or newer of 'bottleneck' (version '1.3.2' currently installed).\n",
      "  from pandas.core import (\n"
     ]
    }
   ],
   "source": [
    "import streamlit as st\n",
    "import os\n",
    "from langchain.tools import DuckDuckGoSearchRun\n",
    "from langchain import hub\n",
    "from langchain.agents import create_openai_functions_agent\n",
    "from langchain_openai import AzureChatOpenAI\n",
    "from langgraph.prebuilt import create_agent_executor\n",
    "from langchain_core.pydantic_v1 import BaseModel\n",
    "from langchain.chains.openai_functions import create_structured_output_runnable\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.pydantic_v1 import BaseModel, Field\n",
    "from typing import Annotated, Any, Dict, Optional, Sequence, TypedDict, List, Tuple\n",
    "import operator"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1089d1df",
   "metadata": {},
   "source": [
    "## Define Environment Variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "eb096563",
   "metadata": {},
   "outputs": [],
   "source": [
    "langchain_api_key = '<api key>'\n",
    "os.environ[\"LANGCHAIN_TRACING_V2\"] = 'true'\n",
    "os.environ[\"LANGCHAIN_ENDPOINT\"] = \"https://api.smith.langchain.com\"\n",
    "os.environ[\"LANGCHAIN_API_KEY\"] = langchain_api_key\n",
    "os.environ[\"LANGCHAIN_PROJECT\"] =\"multi-agent\"\n",
    "os.environ[\"AZURE_OPENAI_ENDPOINT\"] = \"<azure openai endpoint>\"\n",
    "os.environ[\"AZURE_OPENAI_API_KEY\"] = \"<azure openai api key>\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d2f01b08",
   "metadata": {},
   "outputs": [],
   "source": [
    "llm = AzureChatOpenAI(temperature=0, \n",
    "                          max_tokens=1024,openai_api_version=\"2023-07-01-preview\",\n",
    "    azure_deployment=\"gpt-4-1106-preview\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23d98a4f",
   "metadata": {},
   "source": [
    "## Graph Node - Programmer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5d692412",
   "metadata": {},
   "source": [
    "#### Programmer Agent - Specialized in Writing Program based on Requirements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "a7bebfac",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Code(BaseModel):\n",
    "    \"\"\"Plan to follow in future\"\"\"\n",
    "\n",
    "    code: str = Field(\n",
    "        description=\"Detailed optmized error-free Python code on the provided requirements\"\n",
    "    )\n",
    "    \n",
    "\n",
    "from langchain.chains.openai_functions import create_structured_output_runnable\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "code_gen_prompt = ChatPromptTemplate.from_template(\n",
    "    '''**Role**: You are a expert software python programmer. You need to develop python code\n",
    "**Task**: As a programmer, you are required to complete the function. Use a Chain-of-Thought approach to break\n",
    "down the problem, create pseudocode, and then write the code in Python language. Ensure that your code is\n",
    "efficient, readable, and well-commented.\n",
    "\n",
    "**Instructions**:\n",
    "1. **Understand and Clarify**: Make sure you understand the task.\n",
    "2. **Algorithm/Method Selection**: Decide on the most efficient way.\n",
    "3. **Pseudocode Creation**: Write down the steps you will follow in pseudocode.\n",
    "4. **Code Generation**: Translate your pseudocode into executable Python code\n",
    "\n",
    "*REQURIEMENT*\n",
    "{requirement}'''\n",
    ")\n",
    "coder = create_structured_output_runnable(\n",
    "    Code, llm, code_gen_prompt\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "f4b87069",
   "metadata": {},
   "outputs": [],
   "source": [
    "code_ = coder.invoke({'requirement':'Generate fibbinaco series'})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95ab5d77",
   "metadata": {},
   "source": [
    "## Graph Node - Tester"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e7bfa42",
   "metadata": {},
   "source": [
    "#### Tester Agent - Generates input test cases and expected output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "f3902cae",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Test(BaseModel):\n",
    "    \"\"\"Plan to follow in future\"\"\"\n",
    "\n",
    "    Input: List[List] = Field(\n",
    "        description=\"Input for Test cases to evaluate the provided code\"\n",
    "    )\n",
    "    Output: List[List] = Field(\n",
    "        description=\"Expected Output for Test cases to evaluate the provided code\"\n",
    "    )\n",
    "    \n",
    "\n",
    "from langchain.chains.openai_functions import create_structured_output_runnable\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "test_gen_prompt = ChatPromptTemplate.from_template(\n",
    "    '''**Role**: As a tester, your task is to create Basic and Simple test cases based on provided Requirement and Python Code. \n",
    "These test cases should encompass Basic, Edge scenarios to ensure the code's robustness, reliability, and scalability.\n",
    "**1. Basic Test Cases**:\n",
    "- **Objective**: Basic and Small scale test cases to validate basic functioning \n",
    "**2. Edge Test Cases**:\n",
    "- **Objective**: To evaluate the function's behavior under extreme or unusual conditions.\n",
    "**Instructions**:\n",
    "- Implement a comprehensive set of test cases based on requirements.\n",
    "- Pay special attention to edge cases as they often reveal hidden bugs.\n",
    "- Only Generate Basics and Edge cases which are small\n",
    "- Avoid generating Large scale and Medium scale test case. Focus only small, basic test-cases\n",
    "*REQURIEMENT*\n",
    "{requirement}\n",
    "**Code**\n",
    "{code}\n",
    "'''\n",
    ")\n",
    "tester_agent = create_structured_output_runnable(\n",
    "    Test, llm, test_gen_prompt\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "4794c86b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Chain of Thought\n",
      "# 1. Understand and Clarify: The task is to generate the Fibonacci series.\n",
      "# 2. Algorithm/Method Selection: Use an iterative approach to generate the series efficiently.\n",
      "# 3. Pseudocode Creation:\n",
      "#    - Initialize the first two numbers of the series: 0 and 1.\n",
      "#    - Use a loop to generate the next numbers in the series.\n",
      "#    - For each iteration, calculate the next number by summing the last two numbers.\n",
      "#    - Update the last two numbers with the new values.\n",
      "# 4. Code Generation:\n",
      "\n",
      "# Function to generate Fibonacci series up to n terms\n",
      "\n",
      "def generate_fibonacci(n):\n",
      "    # Initialize the first two numbers\n",
      "    a, b = 0, 1\n",
      "    series = []\n",
      "\n",
      "    # Generate the series up to n terms\n",
      "    for _ in range(n):\n",
      "        series.append(a)\n",
      "        # Update the last two numbers\n",
      "        a, b = b, a + b\n",
      "\n",
      "    return series\n",
      "\n",
      "# Example usage:\n",
      "# Generate the first 10 terms of the Fibonacci series\n",
      "print(generate_fibonacci(10))\n"
     ]
    }
   ],
   "source": [
    "print(code_.code)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "087dcc13",
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "test_ = tester_agent.invoke({'requirement':'Generate fibbinaco series','code':code_.code})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "3981798a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Test(Input=[[0], [1], [2], [5], [10], [-1], [1.5], ['three'], [None]], Output=[[[]], [[0]], [[0, 1]], [[0, 1, 1, 2, 3]], [[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]], [[]], [[]], [[]], [[]]])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6c9e3c6",
   "metadata": {},
   "source": [
    "## Graph Node - Python Executor"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89fd5bbf",
   "metadata": {},
   "source": [
    "#### Executor - Executes code in a Python environment on provided test cases"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "42b9fda3",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ExecutableCode(BaseModel):\n",
    "    \"\"\"Plan to follow in future\"\"\"\n",
    "\n",
    "    code: str = Field(\n",
    "        description=\"Detailed optmized error-free Python code with test cases assertion\"\n",
    "    )\n",
    "\n",
    "python_execution_gen = ChatPromptTemplate.from_template(\n",
    "    \"\"\"You have to add testing layer in the *Python Code* that can help to execute the code. You need to pass only Provided Input as argument and validate if the Given Expected Output is matched.\n",
    "*Instruction*:\n",
    "- Make sure to return the error if the assertion fails\n",
    "- Generate the code that can be execute\n",
    "Python Code to excecute:\n",
    "*Python Code*:{code}\n",
    "Input and Output For Code:\n",
    "*Input*:{input}\n",
    "*Expected Output*:{output}\"\"\"\n",
    ")\n",
    "execution = create_structured_output_runnable(\n",
    "    ExecutableCode, llm, python_execution_gen\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "65b58139",
   "metadata": {},
   "outputs": [],
   "source": [
    "code_execute = execution.invoke({\"code\":code_.code,\"input\":test_.Input,'output':test_.Output})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "f50e5c97",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Chain of Thought\n",
      "# 1. Understand and Clarify: The task is to generate the Fibonacci series.\n",
      "# 2. Algorithm/Method Selection: Use an iterative approach to generate the series efficiently.\n",
      "# 3. Pseudocode Creation:\n",
      "#    - Initialize the first two numbers of the series: 0 and 1.\n",
      "#    - Use a loop to generate the next numbers in the series.\n",
      "#    - For each iteration, calculate the next number by summing the last two numbers.\n",
      "#    - Update the last two numbers with the new values.\n",
      "# 4. Code Generation:\n",
      "\n",
      "# Function to generate Fibonacci series up to n terms\n",
      "\n",
      "def generate_fibonacci(n):\n",
      "    # Initialize the first two numbers\n",
      "    a, b = 0, 1\n",
      "    series = []\n",
      "\n",
      "    # Generate the series up to n terms\n",
      "    for _ in range(n):\n",
      "        series.append(a)\n",
      "        # Update the last two numbers\n",
      "        a, b = b, a + b\n",
      "\n",
      "    return series\n",
      "\n",
      "# Testing layer\n",
      "\n",
      "def test_generate_fibonacci():\n",
      "    test_cases = [\n",
      "        ([0], []),\n",
      "        ([1], [0]),\n",
      "        ([2], [0, 1]),\n",
      "        ([5], [0, 1, 1, 2, 3]),\n",
      "        ([10], [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]),\n",
      "        ([-1], []),\n",
      "        ([1.5], []),\n",
      "        (['three'], []),\n",
      "        ([None], [])\n",
      "    ]\n",
      "\n",
      "    for inputs, expected in test_cases:\n",
      "        result = generate_fibonacci(*inputs)\n",
      "        assert result == expected, f'Error on test case {inputs}, expected {expected}, got {result}'\n",
      "\n",
      "    print(\"All test cases passed!\")\n",
      "\n",
      "test_generate_fibonacci()\n"
     ]
    }
   ],
   "source": [
    "print(code_execute.code)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "9397a93c",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Exception : 'float' object cannot be interpreted as an integer\""
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "error = None\n",
    "try:\n",
    "    exec(code_execute.code)\n",
    "except Exception as e:\n",
    "    error = f'Exception : {e}'\n",
    "error"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73c2021c",
   "metadata": {},
   "source": [
    "## Graph Node -Debugger"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "451bb1c5",
   "metadata": {},
   "source": [
    "#### Debugger - Debugs code using LLM knowledge and sends it back to the 'Executer' Agent in case of errors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "a1fa1a5e",
   "metadata": {},
   "outputs": [],
   "source": [
    "class RefineCode(BaseModel):\n",
    "\n",
    "    code: str = Field(\n",
    "        description=\"Optimized and Refined Python code to resolve the error\"\n",
    "    )\n",
    "    \n",
    "\n",
    "python_refine_gen = ChatPromptTemplate.from_template(\n",
    "    \"\"\"You are expert in Python Debugging. You have to analysis Given Code and Error and generate code that handles the error\n",
    "    *Instructions*:\n",
    "    - Make sure to generate error free code\n",
    "    - Generated code is able to handle the error\n",
    "    \n",
    "    *Code*: {code}\n",
    "    *Error*: {error}\n",
    "    \"\"\"\n",
    ")\n",
    "refine_code = create_structured_output_runnable(\n",
    "    RefineCode, llm, python_refine_gen\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "0c5b5fd8",
   "metadata": {},
   "outputs": [],
   "source": [
    "dummy_json = {\n",
    "    \"code\": code_execute.code,\n",
    "    \"error\": error\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "6e7fdf63",
   "metadata": {},
   "outputs": [],
   "source": [
    "refine_code_ = refine_code.invoke(dummy_json)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "a39a6514",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# Function to generate Fibonacci series up to n terms\n",
      "\n",
      "def generate_fibonacci(n):\n",
      "    # Check if n is an integer and greater than 0\n",
      "    if not isinstance(n, int) or n <= 0:\n",
      "        return []\n",
      "\n",
      "    # Initialize the first two numbers\n",
      "    a, b = 0, 1\n",
      "    series = []\n",
      "\n",
      "    # Generate the series up to n terms\n",
      "    for _ in range(n):\n",
      "        series.append(a)\n",
      "        # Update the last two numbers\n",
      "        a, b = b, a + b\n",
      "\n",
      "    return series\n",
      "\n",
      "# Testing layer\n",
      "\n",
      "def test_generate_fibonacci():\n",
      "    test_cases = [\n",
      "        (0, []),\n",
      "        (1, [0]),\n",
      "        (2, [0, 1]),\n",
      "        (5, [0, 1, 1, 2, 3]),\n",
      "        (10, [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]),\n",
      "        (-1, []),\n",
      "        (1.5, []),\n",
      "        ('three', []),\n",
      "        (None, [])\n",
      "    ]\n",
      "\n",
      "    for inputs, expected in test_cases:\n",
      "        result = generate_fibonacci(inputs)\n",
      "        assert result == expected, f'Error on test case {inputs}, expected {expected}, got {result}'\n",
      "\n",
      "    print(\"All test cases passed!\")\n",
      "\n",
      "test_generate_fibonacci()\n"
     ]
    }
   ],
   "source": [
    "print(refine_code_.code)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "9c44d93a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "All test cases passed!\n"
     ]
    }
   ],
   "source": [
    "exec(refine_code_.code)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bda90aa",
   "metadata": {},
   "source": [
    "## Graph Design"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "2f6276e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "class AgentCoder(TypedDict):\n",
    "    requirement: str\n",
    "    code: str\n",
    "    tests: Dict[str, any]\n",
    "    errors: Optional[str]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "cb6dff71",
   "metadata": {},
   "outputs": [],
   "source": [
    "def programmer(state):\n",
    "    print(f'Entering in Programmer')\n",
    "    requirement = state['requirement']\n",
    "    code_ = coder.invoke({'requirement':requirement})\n",
    "    return {'code':code_.code}\n",
    "\n",
    "def debugger(state):\n",
    "    print(f'Entering in Debugger')\n",
    "    errors = state['errors']\n",
    "    code = state['code']\n",
    "    refine_code_ = refine_code.invoke({'code':code,'error':errors})\n",
    "    return {'code':refine_code_.code,'errors':None}\n",
    "\n",
    "def executer(state):\n",
    "    print(f'Entering in Executer')\n",
    "    tests = state['tests']\n",
    "    input_ = tests['input']\n",
    "    output_ = tests['output']\n",
    "    code = state['code']\n",
    "    executable_code = execution.invoke({\"code\":code,\"input\":input_,'output':output_})\n",
    "    #print(f\"Executable Code - {executable_code.code}\")\n",
    "    error = None\n",
    "    try:\n",
    "        exec(executable_code.code)\n",
    "        print(\"Code Execution Successful\")\n",
    "    except Exception as e:\n",
    "        print('Found Error While Running')\n",
    "        error = f\"Execution Error : {e}\"\n",
    "    return {'code':executable_code.code,'errors':error}\n",
    "\n",
    "def tester(state):\n",
    "    print(f'Entering in Tester')\n",
    "    requirement = state['requirement']\n",
    "    code = state['code']\n",
    "    tests = tester_agent.invoke({'requirement':requirement,'code':code})\n",
    "    #tester.invoke({'requirement':'Generate fibbinaco series','code':code_.code})\n",
    "    return {'tests':{'input':tests.Input,'output':tests.Output}}\n",
    "\n",
    "def decide_to_end(state):\n",
    "    print(f'Entering in Decide to End')\n",
    "    if state['errors']:\n",
    "        return 'debugger'\n",
    "    else:\n",
    "        return 'end'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "40b0b9f8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langgraph.graph import END, StateGraph\n",
    "\n",
    "workflow = StateGraph(AgentCoder)\n",
    "\n",
    "# Define the nodes\n",
    "workflow.add_node(\"programmer\", programmer)  \n",
    "workflow.add_node(\"debugger\", debugger) \n",
    "workflow.add_node(\"executer\", executer) \n",
    "workflow.add_node(\"tester\", tester) \n",
    "#workflow.add_node('decide_to_end',decide_to_end)\n",
    "\n",
    "# Build graph\n",
    "workflow.set_entry_point(\"programmer\")\n",
    "workflow.add_edge(\"programmer\", \"tester\")\n",
    "workflow.add_edge(\"debugger\", \"executer\")\n",
    "workflow.add_edge(\"tester\", \"executer\")\n",
    "#workflow.add_edge(\"executer\", \"decide_to_end\")\n",
    "\n",
    "workflow.add_conditional_edges(\n",
    "    \"executer\",\n",
    "    decide_to_end,\n",
    "    {\n",
    "        \"end\": END,\n",
    "        \"debugger\": \"debugger\",\n",
    "    },\n",
    ")\n",
    "\n",
    "# Compile\n",
    "app = workflow.compile()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2f216b2",
   "metadata": {},
   "source": [
    "- Running Leetcode Problem (https://leetcode.com/problems/two-sum/description/) \n",
    "- It should generate test-cases to evaluate the solution\n",
    "- The solution should be optimized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "eabce06d",
   "metadata": {},
   "outputs": [],
   "source": [
    "requirement = \"\"\"Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume that each input would have exactly one solution, and you may not use the same element twice.You can return the answer in any order.\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "81417f7b",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Entering in Programmer\n",
      "{'code': '# Understand and Clarify:\\n# The task is to find two numbers in the array that add up to the target value.\\n# Each input is guaranteed to have one solution, and we cannot use the same element twice.\\n\\n# Algorithm/Method Selection:\\n# A hash map (dictionary in Python) can be used for efficient lookup of the complement of each element.\\n# We iterate through the array, and for each element, we check if the complement (target - element) is in the map.\\n# If it is, we return the current index and the index stored in the map.\\n# If not, we add the element and its index to the map.\\n\\n# Pseudocode Creation:\\n# 1. Initialize an empty dictionary to store elements and their indices.\\n# 2. Iterate through the array with both index and value.\\n# 3. Calculate the complement by subtracting the current value from the target.\\n# 4. Check if the complement is in the dictionary.\\n#    - If yes, return the current index and the index from the dictionary.\\n#    - If no, add the current value and index to the dictionary.\\n\\n# Code Generation:\\ndef two_sum(nums, target):\\n    num_dict = {}\\n    for index, num in enumerate(nums):\\n        complement = target - num\\n        if complement in num_dict:\\n            return [num_dict[complement], index]\\n        num_dict[num] = index\\n\\n    # Since the problem statement guarantees exactly one solution, we do not need to handle the case\\n    # where no solution is found. The loop will always return before it completes if the input is valid.\\n\\n# Example usage:\\n# two_sum([2, 7, 11, 15], 9) should return [0, 1] because nums[0] + nums[1] == 9'}\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Entering in Tester\n",
      "{'tests': {'input': [[[2, 7, 11, 15], 9], [[3, 2, 4], 6], [[0, 4, 3, 0], 0], [[-1, -2, -3, -4, -5], -8]], 'output': [[[0, 1]], [[1, 2]], [[0, 3]], [[2, 4]]]}}\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Entering in Executer\n",
      "Test passed for input [[2, 7, 11, 15], 9]: expected [0, 1], got [0, 1]\n",
      "Test passed for input [[3, 2, 4], 6]: expected [1, 2], got [1, 2]\n",
      "Test passed for input [[0, 4, 3, 0], 0]: expected [0, 3], got [0, 3]\n",
      "Test passed for input [[-1, -2, -3, -4, -5], -8]: expected [2, 4], got [2, 4]\n",
      "Code Execution Successful\n",
      "{'code': \"def two_sum(nums, target):\\n    num_dict = {}\\n    for index, num in enumerate(nums):\\n        complement = target - num\\n        if complement in num_dict:\\n            return [num_dict[complement], index]\\n        num_dict[num] = index\\n\\n# Testing layer\\nif __name__ == '__main__':\\n    test_cases = [\\n        ([[2, 7, 11, 15], 9], [0, 1]),\\n        ([[3, 2, 4], 6], [1, 2]),\\n        ([[0, 4, 3, 0], 0], [0, 3]),\\n        ([[-1, -2, -3, -4, -5], -8], [2, 4])\\n    ]\\n\\n    for inputs, expected in test_cases:\\n        result = two_sum(*inputs)\\n        assert result == expected, f'Test failed for input {inputs}: expected {expected}, got {result}'\\n        print(f'Test passed for input {inputs}: expected {expected}, got {result}')\\n\", 'errors': None}\n",
      "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n",
      "Entering in Decide to End\n"
     ]
    }
   ],
   "source": [
    "from langchain_core.messages import HumanMessage\n",
    "\n",
    "config = {\"recursion_limit\": 50}\n",
    "inputs = {\"requirement\": requirement}\n",
    "running_dict = {}\n",
    "async for event in app.astream(inputs, config=config):\n",
    "    for k, v in event.items():\n",
    "        running_dict[k] = v\n",
    "        if k != \"__end__\":\n",
    "            print(v)\n",
    "            print('----------'*20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "58dade0f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume that each input would have exactly one solution, and you may not use the same element twice.You can return the answer in any order.\n"
     ]
    }
   ],
   "source": [
    "print(v['requirement'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "d9b43f2e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "def two_sum(nums, target):\n",
      "    num_dict = {}\n",
      "    for index, num in enumerate(nums):\n",
      "        complement = target - num\n",
      "        if complement in num_dict:\n",
      "            return [num_dict[complement], index]\n",
      "        num_dict[num] = index\n",
      "\n",
      "# Testing layer\n",
      "if __name__ == '__main__':\n",
      "    test_cases = [\n",
      "        ([[2, 7, 11, 15], 9], [0, 1]),\n",
      "        ([[3, 2, 4], 6], [1, 2]),\n",
      "        ([[0, 4, 3, 0], 0], [0, 3]),\n",
      "        ([[-1, -2, -3, -4, -5], -8], [2, 4])\n",
      "    ]\n",
      "\n",
      "    for inputs, expected in test_cases:\n",
      "        result = two_sum(*inputs)\n",
      "        assert result == expected, f'Test failed for input {inputs}: expected {expected}, got {result}'\n",
      "        print(f'Test passed for input {inputs}: expected {expected}, got {result}')\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(v['code'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "7ba4f3bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'programmer': {'code': '# Understand and Clarify:\\n# The task is to find two numbers in the array that add up to the target value.\\n# Each input is guaranteed to have one solution, and we cannot use the same element twice.\\n\\n# Algorithm/Method Selection:\\n# A hash map (dictionary in Python) can be used for efficient lookup of the complement of each element.\\n# We iterate through the array, and for each element, we check if the complement (target - element) is in the map.\\n# If it is, we return the current index and the index stored in the map.\\n# If not, we add the element and its index to the map.\\n\\n# Pseudocode Creation:\\n# 1. Initialize an empty dictionary to store elements and their indices.\\n# 2. Iterate through the array with both index and value.\\n# 3. Calculate the complement by subtracting the current value from the target.\\n# 4. Check if the complement is in the dictionary.\\n#    - If yes, return the current index and the index from the dictionary.\\n#    - If no, add the current value and index to the dictionary.\\n\\n# Code Generation:\\ndef two_sum(nums, target):\\n    num_dict = {}\\n    for index, num in enumerate(nums):\\n        complement = target - num\\n        if complement in num_dict:\\n            return [num_dict[complement], index]\\n        num_dict[num] = index\\n\\n    # Since the problem statement guarantees exactly one solution, we do not need to handle the case\\n    # where no solution is found. The loop will always return before it completes if the input is valid.\\n\\n# Example usage:\\n# two_sum([2, 7, 11, 15], 9) should return [0, 1] because nums[0] + nums[1] == 9'},\n",
       " 'tester': {'tests': {'input': [[[2, 7, 11, 15], 9],\n",
       "    [[3, 2, 4], 6],\n",
       "    [[0, 4, 3, 0], 0],\n",
       "    [[-1, -2, -3, -4, -5], -8]],\n",
       "   'output': [[[0, 1]], [[1, 2]], [[0, 3]], [[2, 4]]]}},\n",
       " 'executer': {'code': \"def two_sum(nums, target):\\n    num_dict = {}\\n    for index, num in enumerate(nums):\\n        complement = target - num\\n        if complement in num_dict:\\n            return [num_dict[complement], index]\\n        num_dict[num] = index\\n\\n# Testing layer\\nif __name__ == '__main__':\\n    test_cases = [\\n        ([[2, 7, 11, 15], 9], [0, 1]),\\n        ([[3, 2, 4], 6], [1, 2]),\\n        ([[0, 4, 3, 0], 0], [0, 3]),\\n        ([[-1, -2, -3, -4, -5], -8], [2, 4])\\n    ]\\n\\n    for inputs, expected in test_cases:\\n        result = two_sum(*inputs)\\n        assert result == expected, f'Test failed for input {inputs}: expected {expected}, got {result}'\\n        print(f'Test passed for input {inputs}: expected {expected}, got {result}')\\n\",\n",
       "  'errors': None},\n",
       " '__end__': {'requirement': 'Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume that each input would have exactly one solution, and you may not use the same element twice.You can return the answer in any order.',\n",
       "  'code': \"def two_sum(nums, target):\\n    num_dict = {}\\n    for index, num in enumerate(nums):\\n        complement = target - num\\n        if complement in num_dict:\\n            return [num_dict[complement], index]\\n        num_dict[num] = index\\n\\n# Testing layer\\nif __name__ == '__main__':\\n    test_cases = [\\n        ([[2, 7, 11, 15], 9], [0, 1]),\\n        ([[3, 2, 4], 6], [1, 2]),\\n        ([[0, 4, 3, 0], 0], [0, 3]),\\n        ([[-1, -2, -3, -4, -5], -8], [2, 4])\\n    ]\\n\\n    for inputs, expected in test_cases:\\n        result = two_sum(*inputs)\\n        assert result == expected, f'Test failed for input {inputs}: expected {expected}, got {result}'\\n        print(f'Test passed for input {inputs}: expected {expected}, got {result}')\\n\",\n",
       "  'tests': {'input': [[[2, 7, 11, 15], 9],\n",
       "    [[3, 2, 4], 6],\n",
       "    [[0, 4, 3, 0], 0],\n",
       "    [[-1, -2, -3, -4, -5], -8]],\n",
       "   'output': [[[0, 1]], [[1, 2]], [[0, 3]], [[2, 4]]]},\n",
       "  'errors': None}}"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "running_dict"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
